package cn.czh0123.service.impl;

import cn.czh0123.constants.UploadDirectories;
import cn.czh0123.domain.*;
import cn.czh0123.dto.UploadImageInfo;
import cn.czh0123.dto.WallpaperDTO;
import cn.czh0123.enums.WallpaperOperateType;
import cn.czh0123.enums.WallpaperStatus;
import cn.czh0123.exception.BusinessException;
import cn.czh0123.mapper.*;
import cn.czh0123.msg.WallpaperCodeMsg;
import cn.czh0123.query.WallpaperCategoryQuery;
import cn.czh0123.query.WallpaperQuery;
import cn.czh0123.redis.service.IWallpaperOperateRedisService;
import cn.czh0123.redis.service.IWallpaperStatisticsRedisService;
import cn.czh0123.service.IMinioService;
import cn.czh0123.service.IWallpaperService;
import cn.czh0123.redis.vo.WallpaperStatisticsVO;
import cn.czh0123.vo.WallpaperVO;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* 壁纸服务接口实现
*/
@Service
@Transactional
public class WallpaperServiceImpl extends ServiceImpl<WallpaperMapper,Wallpaper> implements IWallpaperService  {

    @Resource
    private WallpaperMapper wallpaperMapper;
    @Resource
    private WallpaperCategoryMapper wallpaperCategoryMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private IWallpaperOperateRedisService wallpaperOperateRedisService;
    @Resource
    private IWallpaperStatisticsRedisService wallpaperStatisticsRedisService;
    @Resource
    private IMinioService minioService;

    @Override
    public IPage<Wallpaper> queryPage(WallpaperQuery qo) {
        IPage<Wallpaper> page = new Page<>(qo.getCurrentPage(), qo.getPageSize());
        return super.page(page, Wrappers.<Wallpaper>lambdaQuery().eq(Wallpaper::getStatus, WallpaperStatus.APPROVED.getCode()));
    }

    @Override
    public List<Wallpaper> queryCarousel() {
        // TODO 后续改为下载量前6的热门壁纸
        List<Wallpaper> wallpapers = wallpaperMapper.selectList(Wrappers.<Wallpaper>lambdaQuery().eq(Wallpaper::getStatus, WallpaperStatus.APPROVED.getCode()));
        Collections.shuffle(wallpapers);
        return Lists.newArrayList(wallpapers.subList(0, Math.min(6, wallpapers.size())));
    }

    @Override
    public WallpaperVO getWallpaperDetail(Long id) {
        Wallpaper wallpaper = wallpaperMapper.selectById(id);
        if (wallpaper == null) {
            throw new BusinessException(WallpaperCodeMsg.NOT_FOUND_WALLPAPER);
        }
        // 浏览量+1
        wallpaperOperateRedisService.operate(id, WallpaperOperateType.VIEW);

        WallpaperVO wallpaperVO = new WallpaperVO();
        wallpaperVO.setId(wallpaper.getId());
        wallpaperVO.setUrl(wallpaper.getImageUrl());
        wallpaperVO.setTitle(wallpaper.getTitle());
        wallpaperVO.setResolution(wallpaper.getResolution());

        // 作者
        Optional<User> optionalUploader = Optional.ofNullable(userMapper.selectById(wallpaper.getUploaderUserId()));
        if (optionalUploader.isPresent()) {
            User uploader = optionalUploader.get();
            wallpaperVO.setAuthorId(wallpaper.getUploaderUserId());
            wallpaperVO.setAuthor(uploader.getUsername());
        }

        // 分类
        String[] categoryIds = Optional.ofNullable(wallpaper.getCategoryIds()).orElse("").split(",");
        List<Long> categoryIdList = Arrays.stream(categoryIds)
                .filter(categoryId -> !categoryId.isEmpty())
                .map(Long::parseLong)
                .collect(Collectors.toList());
        if (!categoryIdList.isEmpty()) {
            List<WallpaperCategory> categories = wallpaperCategoryMapper.selectBatchIds(categoryIdList);
            wallpaperVO.setCategories(categories);
        }

        // 统计
        WallpaperStatisticsVO statisticsVO = wallpaperStatisticsRedisService.getWallpaperStatistics(id);
        wallpaperVO.setWallpaperStatisticsVO(statisticsVO);

        return wallpaperVO;
    }

    @Override
    public void saveWallpaper(WallpaperDTO dto) {
        Wallpaper wallpaper = new Wallpaper();
        String loginId = StpUtil.getLoginId().toString();
        wallpaper.setUploaderUserId(Long.parseLong(loginId));

        UploadImageInfo imageInfo = minioService.uploadFile(UploadDirectories.WALLPAPER, dto.getFile());
        wallpaper.setImageUrl(imageInfo.getUrl());
        wallpaper.setSize(imageInfo.getSize());
        wallpaper.setResolution(Joiner.on("*").join(imageInfo.getWidth(), imageInfo.getHeight()));

        wallpaper.setTitle(dto.getTitle());
        wallpaper.setStatus(WallpaperStatus.PENDING_REVIEW.getCode());
        wallpaper.setCategoryIds(dto.getCategoryIds());
        wallpaper.setUploadTime(new Date());

        wallpaperMapper.insert(wallpaper);
    }

    @Override
    public IPage<Map<String, Object>> getCategory(WallpaperCategoryQuery query) {
        LambdaQueryWrapper<WallpaperCategory> wrapper = Wrappers.<WallpaperCategory>lambdaQuery()
                .eq(query.getId() != null, WallpaperCategory::getId, query.getId())
                .eq(query.getParentId() != null, WallpaperCategory::getParentCategoryId, query.getParentId())
                .like(StringUtils.isNoneBlank(query.getName()), WallpaperCategory::getName, query.getName());
        // 分页查询
        IPage<Map<String, Object>> page = wallpaperCategoryMapper.selectMapsPage(
                new Page<>(query.getCurrentPage(), query.getPageSize()), wrapper);

        // 加载所有类别到内存中
        Map<Long, WallpaperCategory> categoryMap = wallpaperCategoryMapper.selectList(null)
                .stream().collect(Collectors.toMap(WallpaperCategory::getId, Function.identity()));

        // 使用内存中的数据构建面包屑
        for (Map<String, Object> record : page.getRecords()) {
            Object idObj = record.get("id");
            if (idObj != null) {
                Long id = Long.parseLong(idObj.toString());
                String breadcrumb = getBreadcrumb(id, categoryMap); // 修改getBreadcrumb以便传对象
                record.put("breadcrumb", breadcrumb);
            }
        }
        return page;
    }

    private String getBreadcrumb(Long categoryId, Map<Long, WallpaperCategory> categoryMap) {
        List<String> names = new ArrayList<>();

        while (categoryId != null) {
            WallpaperCategory category = categoryMap.get(categoryId);
            if (category != null) {
                names.add(0, category.getName());
                categoryId = category.getParentCategoryId();
            } else {
                break;
            }
        }

        if(!names.isEmpty()) {
            names.remove(names.size() - 1);
        }

        return String.join(" > ", names);
    }
}
